﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using _PLATFORM.DATA;

namespace _PLATFORM.WEB.Controllers
{ 
    public class SelectionOptionController : Controller
    {
        private eCommPlatformRepoEntities db = new eCommPlatformRepoEntities();

        private static string ProductType { get; set; }
        private static Guid? UserID { get; set; }

        

        //
        // GET: /SelectionOption/

        public ViewResult Index(string productType = null)
        {
            UserID = _PLATFORM.DATA.Custom_Classes.User.UserID;
            var groups = db.GROUPs.OrderBy(g => g.ORDER).Where(g => g.USER_ID == UserID);
            ViewBag.Groups = groups;

            var selection_option = db.SELECTION_OPTION.Where(s => s.USER_ID == UserID);
            ViewBag.SelectionOptions = selection_option;

            // Get the Products
            ProductType = productType ?? "Component";
            var queryResults = db.Get_Products_By_Type_For_Users(ProductType, UserID ?? UserID);
            var listOfProducts = queryResults.Select(result => new PRODUCT { NAME = result.NAME, PRODUCT_ID = result.PRODUCT_ID });
            ViewBag.ProductSelectList = listOfProducts;
            ViewBag.ProductType = ProductType;

            return View();
        }

        public ActionResult RenderMatrix()
        {
            var returnString = "";

            // Get Current Selection Options
            var selectionPaths = db.Get_All_Selection_Options_By_Product_Type_And_User(ProductType, UserID).ToList();

            // Get the Unique Paths
            var paths = selectionPaths.Select(row => decimal.Parse(row.PATH_ID.ToString())).ToList().Distinct();

            // Get the Group Information for each Path
            var pathGroups = new Dictionary<decimal, List<Dictionary<Dictionary<decimal, string>, Dictionary<decimal, string>>>>();

            var pathProducts = new Dictionary<decimal, Dictionary<decimal, string>>();

            foreach (var path in paths)
            {
                var pathID = path;
                // Get the GROUP for this PATH
                var groupIDs = selectionPaths.Where(p => p.PATH_ID == path).Select(g => g.GROUP_ID).ToList().Distinct();

                var pathGroupList = new List<Dictionary<Dictionary<decimal, string>, Dictionary<decimal, string>>>();

                // Get the GROUP NAME
                foreach (var gID in groupIDs)
                {
                    

                    var groupID = decimal.Parse(gID.ToString());

                    var grpNm = selectionPaths.Where(g => g.GROUP_ID == groupID).Where(p => p.PATH_ID == path).Select(n => n.GROUP_NM).ElementAt(0);

                    // Add to Dictionary
                    var groupDict = new Dictionary<decimal, string> { { groupID, grpNm } };

                    var selOptID = selectionPaths.Where(g => g.GROUP_ID == groupID).Where(p => p.PATH_ID == path).Select(n => n.SEL_ID).ElementAt(0);
                    var selOptNm = selectionPaths.Where(g => g.GROUP_ID == groupID).Where(p => p.PATH_ID == path).Select(n => n.SEL_NM).ElementAt(0);

                    var selectionOptDict = new Dictionary<decimal, string> { { decimal.Parse(selOptID.ToString()), selOptNm } };

                    var proxyList = new Dictionary<Dictionary<decimal, string>, Dictionary<decimal, string>> { { groupDict, selectionOptDict } };

                    pathGroupList.Add(proxyList);

                    returnString += string.Format("<li><span class='folder'>{0}</span>", selOptNm);
                    returnString += string.Format("<ul>");

                    //pathGroups.Add(path, pathGroupList);
                }

                // Now get the path products
                var pathRows = selectionPaths.Where(p => p.PATH_ID == path).Select(p => p.PROD_ID).ToList().Distinct();
                var products = new Dictionary<decimal, string>();
                foreach (var pR in pathRows)
                {
                    returnString += string.Format("<li><span class='file'>{0}</span></li>", selectionPaths.Where(p => p.PROD_ID == pR).Select(n => n.PROD_NM).ElementAt(0));
                }

                        //returnString += string.Format("</ul>");
                        //returnString += string.Format("</li>");

                for (var i = 0; i < groupIDs.Count(); i++)
                {
                    returnString += string.Format("</ul>");
                    returnString += string.Format("</li>");
                }
                    

                

                //pathProducts.Add(path, products);

            }

            return Content(returnString);
        }

        public ActionResult RenderMatrix2()
        {
            var returnString = "<ul>";

            ProductType = "Sparepart";
            UserID = new Guid("f2f53f45-0d4f-4af4-97d4-9765dcef561d");

            // Get Current Selection Options
            var selectionPaths = db.Get_All_Selection_Options_By_Product_Type_And_User(ProductType, UserID).ToList();

            // Get the Rows by GROUP_ID
            var uniqueGroupIDs = selectionPaths.Select(g => g.GROUP_ID).ToList().Distinct().ToArray();

            // Get the SELECTION IDs for the 1st GROUP
            var groupOneSelectionIDs_unique = selectionPaths.Where(g => g.GROUP_ID == uniqueGroupIDs.ElementAt(0)).Select(sid => sid.SEL_ID).ToList().Distinct().ToArray();

            var totalGroups = uniqueGroupIDs.Count();

            var currentGroupID = uniqueGroupIDs.ElementAt(0);

            
            foreach (var seed in groupOneSelectionIDs_unique)
            {

                // Rabbit Hole Counter
                var rabbitHoleCounter = 0;

                // How many paths are there for this seed
                // This can be a control variable to ensure that we have went these many
                // levels deep before proceeding to the next seed
                var rabbitHolesToTraverse = selectionPaths.Where(s => s.SEL_ID == seed).Select(p => p.PATH_ID).ToArray();

                var display = selectionPaths.Where(s => s.SEL_ID == seed).Select(s => s.SEL_NM).ElementAt(0);
                returnString += string.Format("<li><span class='folder'>{0}</span>", display);
                returnString += string.Format("<ul>");

                while (rabbitHoleCounter < rabbitHolesToTraverse.Count())
                {
                    // how many groups does this rabbitHole contain
                    var groupsForThisRabbitHole = selectionPaths.Where(p => p.PATH_ID == rabbitHolesToTraverse[rabbitHoleCounter]).Select(g => g.GROUP_ID).ToArray();
                    // 4

                    // For each group
                    for (var i = 1; i < groupsForThisRabbitHole.Count(); i++)
                    {
                        // Determine how many unique selection names exist for this SEED and GROUP
                        var uniquePaths = rabbitHolesToTraverse.Select(path => selectionPaths.Where(p => p.PATH_ID == path).Select(s => s.SEL_NM).ElementAt(0)).ToList();
                        // 2

                        var lastSelectionNameWritten = "";
                        foreach (var uniquePath in uniquePaths)
                        {
                            
                            if (lastSelectionNameWritten != uniquePath)
                            {
                                returnString += string.Format("<li><span class='folder'>{0}</span>", uniquePath);
                                returnString += string.Format("<ul>");
                                rabbitHoleCounter++;
                            }
                            else
                            {
                                // step down
                                // how many paths exist for this selection name option
                                var pathsForThisSelectionNameAndGroup =
                                    selectionPaths.Where(s => s.SEL_NM == uniquePath).Where(
                                        g => g.GROUP_ID == uniqueGroupIDs[i]).Select(p => p.PATH_ID).ToList();

                                // again, get the unique selection names for this path
                                var uniqueSubPaths = pathsForThisSelectionNameAndGroup.Select(subPath => selectionPaths.Where(g => g.GROUP_ID == uniqueGroupIDs[i++]).Where(p => p.PATH_ID == Decimal.Parse(subPath.ToString())).Select(s => s.SEL_NM).ElementAt(0)).ToList();
                                foreach (var usp in uniqueSubPaths)
                                {
                                    returnString += string.Format("<li><span class='folder'>{0}</span>", usp);
                                    returnString += string.Format("<ul>");
                                }
                                rabbitHoleCounter++;
                            }

                            lastSelectionNameWritten = uniquePath;
                        }
                    }
                    // Write the products out for this rabbit hole
                    
                }
                continue; // go to the next seed

                int currentGroupIndexer = 1;

                
                // Get the Branches (PATH_IDs) for this Seed (SEL_ID)
                var branches = selectionPaths.Where(s => s.SEL_ID == seed).Select(p => p.PATH_ID).ToList().Distinct();
                var pathsForSeed = selectionPaths.Where(s => s.SEL_ID == seed).Select(p => p.PATH_ID).ToList().Distinct();
                //var selectionNamesForSeed = pathsForSeed.Select(path => selectionPaths.Where(p => p.PATH_ID == path).Where(g => g.GROUP_ID == uniqueGroupIDs.ElementAt(currentGroupIndexer)).ElementAt(0)).ToList();
                
                foreach (var pathID in branches)
                {
                    currentGroupIndexer = 1;
                    var branchCtr = 0;
                    // now see if there are more groups to follow the branch out with
                    var totalBranches = 0;
                    while (currentGroupIndexer < totalGroups)
                    {
                        
                            // Look in the next GROUP for this PATH to get the Selection Options
                            var sOpt =
                                selectionPaths.Where(g => g.GROUP_ID == uniqueGroupIDs.ElementAt(currentGroupIndexer))
                                .Where(p => p.PATH_ID == pathID).Select(so => so.SEL_NM).ToList().Distinct();
                            totalBranches = sOpt.Count();
                            foreach (var s in sOpt)
                            {
                                returnString += string.Format("<li><span class='folder'>{0}</span>", s);
                                returnString += string.Format("<ul>");
                            }

                            currentGroupIndexer++; // go to the next group
                        
                        branchCtr++;
                    }
                    if(currentGroupIndexer == totalGroups)
                    {
                        currentGroupIndexer = 0;
                        // Let's get the products for this seed and path
                        var products =
                            selectionPaths.Where(p => p.PATH_ID == pathID).Select(p => p.PROD_NM).ToList().Distinct();

                        foreach(var product in products)
                            returnString += string.Format("<li><span class='file'>{0}</span></li>", product);
                    }
                    returnString += string.Format("</ul>");
                    returnString += string.Format("</li>");

                    for (var i = 0; i <= totalBranches; i++)
                    {
                        returnString += string.Format("</ul>");
                        returnString += string.Format("</li>");
                    }
                }

                returnString += string.Format("</ul>");
                returnString += string.Format("</li>");
                
            }

            for (var i = 0; i < groupOneSelectionIDs_unique.Count(); i++)
            {
                returnString += string.Format("</ul>");
                returnString += string.Format("</li>");
            }

                returnString += "<ul>";

            return Content(returnString);
        }

        public ActionResult RenderMatrix3()
        {
            var returnString = "<ul>";

            //ProductType = "Sparepart";
            UserID = DATA.Custom_Classes.User.UserID;

            // Get Current Selection Options
            var selectionPaths = db.Get_All_Selection_Options_By_Product_Type_And_User(ProductType, UserID).ToList();

            // Get the Rows by GROUP_ID
            var uniqueGroupIDs = selectionPaths.Select(g => g.GROUP_ID).ToList().Distinct().ToArray();

            // Get the SELECTION IDs for the 1st GROUP
            var groupOneSelectionIDs_unique = selectionPaths.Where(g => g.GROUP_ID == uniqueGroupIDs.ElementAt(0)).Select(sid => sid.SEL_ID).ToList().Distinct();

            var totalGroups = uniqueGroupIDs.Count();

            //var currentGroupID = uniqueGroupIDs.ElementAt(0);

            foreach (var seed in groupOneSelectionIDs_unique)
            {
                int currentGroupIndexer = 1;

                // Write it out
                var display = selectionPaths.Where(s => s.SEL_ID == seed).Select(s => s.SEL_NM).ElementAt(0);
                returnString += string.Format("<li><span class='folder'>{0}</span>", display);
                returnString += string.Format("<ul>");

                // Because a SEL_ID is unique to each group, i can go back 
                // and find all the PATH_IDs for that SELECTION OPTION
                // This will tell me the #of BRANCHES for each OPTIONS!

                // Get the Branches (PATH_IDs) for this Seed (SEL_ID)
                var branches = selectionPaths.Where(s => s.SEL_ID == seed).Select(p => p.PATH_ID).ToList().Distinct();
                var pathsForSeed = selectionPaths.Where(s => s.SEL_ID == seed).Select(p => p.PATH_ID).ToList().Distinct();
                //var selectionNamesForSeed = pathsForSeed.Select(path => selectionPaths.Where(p => p.PATH_ID == path).Where(g => g.GROUP_ID == uniqueGroupIDs.ElementAt(currentGroupIndexer)).ElementAt(0)).ToList();

                foreach (var pathID in branches)
                {
                    currentGroupIndexer = 1;
                    var branchCtr = 0;
                    // now see if there are more groups to follow the branch out with+
                    var totalBranches = 0;
                    while (currentGroupIndexer < totalGroups)
                    {

                        // Look in the next GROUP for this PATH to get the Selection Options
                        var sOpt =
                            selectionPaths.Where(g => g.GROUP_ID == uniqueGroupIDs.ElementAt(currentGroupIndexer))
                            .Where(p => p.PATH_ID == pathID).Select(so => so.SEL_NM).ToList().Distinct();
                        totalBranches = sOpt.Count();
                        foreach (var s in sOpt)
                        {
                            returnString += string.Format("<li><span class='folder'>{0}</span>", s);
                            returnString += string.Format("<ul>");
                        }

                        currentGroupIndexer++; // go to the next group

                        branchCtr++;
                    }
                    if (currentGroupIndexer == totalGroups)
                    {
                        currentGroupIndexer = 0;
                        // Let's get the products for this seed and path
                        var products =
                            selectionPaths.Where(p => p.PATH_ID == pathID).Select(p => p.PROD_NM).ToList().Distinct();

                        foreach (var product in products)
                            returnString += string.Format("<li><span class='file'>{0}</span></li>", product);
                    }
                    returnString += string.Format("</ul>");
                    returnString += string.Format("</li>");

                    for (var i = 0; i <= totalBranches; i++)
                    {
                        returnString += string.Format("</ul>");
                        returnString += string.Format("</li>");
                    }
                }

                returnString += string.Format("</ul>");
                returnString += string.Format("</li>");

            }

            for (var i = 0; i < groupOneSelectionIDs_unique.Count(); i++)
            {
                returnString += string.Format("</ul>");
                returnString += string.Format("</li>");
            }

            returnString += "<ul>";

            return Content(returnString);
        }

        //
        // GET: /SelectionOption/Details/5

        public ViewResult Details(decimal id)
        {
            SELECTION_OPTION selection_option = db.SELECTION_OPTION.Find(id);
            return View(selection_option);
        }

        //
        // GET: /SelectionOption/Create

        public ActionResult Create(string productType)
        {
            ViewBag.ProductType = productType;

            // Get the GROUPs
            var groups = db.GROUPs.OrderBy(g => g.ORDER).Where(g => g.USER_ID == _PLATFORM.DATA.Custom_Classes.User.UserID);

            ViewBag.GroupList = new SelectList(groups, "GROUP_ID", "NAME");

            //ViewBag.USER_ID = new SelectList(db.FRAMEWORK_USER, "USER_ID", "FIRST_NAME");
            return View();
        } 

        //
        // POST: /SelectionOption/Create

        [HttpPost]
        public ActionResult Create(SELECTION_OPTION selection_option, FormCollection formCollection)
        {
            

            selection_option.USER_ID = _PLATFORM.DATA.Custom_Classes.User.UserID;

            selection_option.GROUP_ID = decimal.Parse(formCollection["GroupList"]);

            #region Try to save the IMAGE & PDF

            var ctr = 0;

            foreach (var files in Request.Files)
            {
                var ticks = DateTime.Now.Ticks.ToString();

                HttpPostedFileBase file = Request.Files[ctr];
                if (file.ContentLength > 0)
                {
                    var pathString = "~/Content/User/";

                    if (file.ContentType.Contains("jp") | file.ContentType.Contains("png") | file.ContentType.Contains("gif"))
                    {
                        selection_option.IMAGE = ticks + file.FileName;
                        pathString += "Images";
                    }

                    var savepath = Server.MapPath(Url.Content(pathString));
                    if (!Directory.Exists(savepath))
                        Directory.CreateDirectory(savepath);
                    var filePath = Path.Combine(@savepath, Path.GetFileName(ticks + file.FileName));
                    file.SaveAs(filePath);
                }
                ctr++;
            }

            #endregion

            try
            {
                if (ModelState.IsValid)
                {
                    db.SELECTION_OPTION.Add(selection_option);
                    try
                    {
                        db.SaveChanges();
                        return RedirectToAction("Index");  
                    }
                    catch (Exception err)
                    {
                        // Get the GROUPs
                        var groups = db.GROUPs.OrderBy(g => g.ORDER);

                        ViewBag.GroupList = new SelectList(groups, "GROUP_ID", "NAME");

                        ViewBag.Message = "SAVE ERROR!!! --> The current 'Name' and 'Group' Already Exist!";

                        return View(selection_option);
                    }
                }
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }

            }
            ViewBag.USER_ID = new SelectList(db.FRAMEWORK_USER, "USER_ID", "FIRST_NAME", selection_option.USER_ID);
            return View(selection_option);
        }
        
        [HttpPost]
        public ActionResult CreatePath(FormCollection formCollection)
        {
            var selectedGroupIDs = new Dictionary<decimal, decimal>();

            var theseGroups = db.GROUPs.OrderBy(g => g.ORDER).Where(g => g.USER_ID == DATA.Custom_Classes.User.UserID).ToList();

            // Create a new PATH
            var path = new PATH();
            path.PATH_ID = 0;
            path.USER_ID = _PLATFORM.DATA.Custom_Classes.User.UserID;

            db.PATHs.Add(path);
            db.SaveChanges();

            var pathID = db.PATHs.Max(p => p.PATH_ID);

            foreach (var g in theseGroups)
            {
                // Find the selected path for this group
                var selectedGroupID = formCollection[g.NAME];

                // Add New PATH_GROUP
                var pathGroup = new PATH_GROUP();
                pathGroup.PATH_GROUP_ID = 0;
                pathGroup.PATH_ID = pathID;
                pathGroup.GROUP_ID = g.GROUP_ID;
                db.PATH_GROUP.Add(pathGroup);
                //db.SaveChanges();

                // Add New PATH_SELECTION_OPTION
                var pathSelectionOption = new PATH_SELECTION_OPTION();
                pathSelectionOption.PATH_SELECTION_OPTION_ID = 0;
                pathSelectionOption.PATH_ID = pathID;
                pathSelectionOption.SELECTION_OPTION_ID = decimal.Parse(selectedGroupID);
                db.PATH_SELECTION_OPTION.Add(pathSelectionOption);
                //db.SaveChanges();

            }

            var selectedProducts = formCollection["ProductsToSelect"].Split(',');

            foreach (var prod in selectedProducts)
            {
                var pathProduct = new PATH_PRODUCT();
                pathProduct.PATH_PRODUCT_ID = 0;
                pathProduct.PRODUCT_ID = decimal.Parse(prod);
                pathProduct.PATH_ID = pathID;
                db.PATH_PRODUCT.Add(pathProduct);
            }

            try
            {
                db.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }

            }
            

            return RedirectToAction("Index", new {productType = ProductType});
        }
        
        public ActionResult IndexList()
        {
            return View(db.SELECTION_OPTION.OrderBy(g => g.GROUP_ID).ToList());
        }

        //
        // GET: /SelectionOption/Edit/5
 
        public ActionResult Edit(decimal id)
        {
            SELECTION_OPTION selection_option = db.SELECTION_OPTION.Find(id);
            //ViewBag.USER_ID = new SelectList(db.FRAMEWORK_USER, "USER_ID", "FIRST_NAME", selection_option.USER_ID);

            // Get the GROUPs
            var groups = db.GROUPs.OrderBy(g => g.ORDER);

            ViewBag.GroupList = new SelectList(groups, "GROUP_ID", "NAME", selection_option.GROUP_ID);

            return View(selection_option);
        }

        //
        // POST: /SelectionOption/Edit/5

        [HttpPost]
        public ActionResult Edit(SELECTION_OPTION selection_option, FormCollection formCollection, string c_img)
        {
            #region Try to save the IMAGE & PDF

            var ctr = 0;
            var imgChanged = false;

            foreach (var files in Request.Files)
            {
                var ticks = DateTime.Now.Ticks.ToString();

                HttpPostedFileBase file = Request.Files[ctr];
                if (file.ContentLength > 0)
                {
                    var pathString = "~/Content/User/";

                    if (file.ContentType.Contains("jp") | file.ContentType.Contains("png") | file.ContentType.Contains("gif"))
                    {
                        selection_option.IMAGE = ticks + file.FileName;
                        pathString += "Images";
                        imgChanged = true;
                    }

                    var savepath = Server.MapPath(Url.Content(pathString));
                    if (!Directory.Exists(savepath))
                        Directory.CreateDirectory(savepath);
                    var filePath = Path.Combine(@savepath, Path.GetFileName(ticks + file.FileName));
                    file.SaveAs(filePath);
                }
                ctr++;
            }

            if (!imgChanged)
            {
                // Go fetch the image
                selection_option.IMAGE = String.IsNullOrEmpty(c_img) ? null : c_img;
            }

            #endregion

            selection_option.USER_ID = _PLATFORM.DATA.Custom_Classes.User.UserID;

            selection_option.GROUP_ID = decimal.Parse(formCollection["GroupList"]);

            try
            {
                if (ModelState.IsValid)
                {
                    db.Entry(selection_option).State = EntityState.Modified;
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {
                        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    }
                }
            }

            ViewBag.USER_ID = new SelectList(db.FRAMEWORK_USER, "USER_ID", "FIRST_NAME", selection_option.USER_ID);
            return View(selection_option);
        }

        //
        // GET: /SelectionOption/Delete/5
 
        public ActionResult Delete(decimal id)
        {
            SELECTION_OPTION selection_option = db.SELECTION_OPTION.Find(id);
            return View(selection_option);
        }

        //
        // POST: /SelectionOption/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(decimal id)
        {            
            SELECTION_OPTION selection_option = db.SELECTION_OPTION.Find(id);
            db.SELECTION_OPTION.Remove(selection_option);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}